import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:multi_image_picker/multi_image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qunaimedical/components/custom_divider.dart';
import 'package:qunaimedical/components/edit_text_field.dart';
import 'package:qunaimedical/components/item_add.dart';
import 'package:qunaimedical/components/item_image_preview.dart';
import 'package:qunaimedical/components/item_option.dart';
import 'package:qunaimedical/components/primary_button.dart';
import 'package:qunaimedical/components/primary_label.dart';
import 'package:qunaimedical/models/consultaion_post_bean.dart';
import 'package:qunaimedical/models/department.dart';
import 'package:qunaimedical/models/list_response.dart';
import 'package:qunaimedical/network/http.dart';
import 'package:qunaimedical/pages/conversations/custom_video_player.dart';
import 'package:qunaimedical/pages/select_doctor.dart';
import 'package:qunaimedical/utils/common_util.dart';
import 'package:qunaimedical/utils/dialog_utils.dart';
import 'package:qunaimedical/utils/log_utils.dart';
import 'package:qunaimedical/utils/sp_utils.dart';
import 'package:qunaimedical/utils/toast_util.dart';
import 'package:qunaimedical/values/constants.dart';
import 'package:qunaimedical/values/urls.dart';
import 'package:sprintf/sprintf.dart';
import 'package:video_thumbnail/video_thumbnail.dart';

/// 预约会诊界面
class ConsultationPage extends StatefulWidget {
  static String routeName = '/consultation';

  @override
  _ConsultationPageState createState() => _ConsultationPageState();
}

class _ConsultationPageState extends State<ConsultationPage> {
  static String _tag = '_ConsultationPageState';
  final _picker = ImagePicker();

  /// 选中的图片
  List<Asset> _images = <Asset>[];

  /// 用户上传的图片路径
  List<String> _uploadedImages = [];
  List<String> _uploadedVideos = [];

  /// 最多选9张图片
  int maxImageCount = 9;

  PickedFile _video;

  /// 当前选中的基本信息索引
  int _department;
  int _type;
  List<int> _timeIndex;

  TextEditingController _themeController = TextEditingController();
  TextEditingController _contentController = TextEditingController();

  /// 科室列表。
  List<Department> _departments = [];

  /// 会诊类型列表。
  List<Department> _consultationTypes = [];

  /// 预约时间相关
  List<DateTime> dateArray = [];

  /// 视频缩略图
  GenThumbnailImage _futureImage;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('预约会诊')),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            child: ListView(
              children: [
                CustomDivider(),
                PrimaryLabel('基本信息'),
                ItemOption(
                  text: '会诊科室：',
                  secondText: _department == null
                      ? '请选择'
                      : _departments[_department].label,
                  secondTextColor: _department == null ? null : Colors.black,
                  onTap: () => _selectDepartment(context),
                ),
                ItemOption(
                  text: '会诊类型：',
                  secondText:
                      _type == null ? '请选择' : _consultationTypes[_type].label,
                  secondTextColor: _type == null ? null : Colors.black,
                  onTap: () => _selectReserveType(context),
                ),
                ItemOption(
                    text: '预约时间：',
                    secondTextColor: _timeIndex == null ? null : Colors.black,
                    secondText: _timeIndex == null
                        ? '请选择'
                        : '${dateArray[_timeIndex[0]].toString().substring(0, 10)} ${Constants.timeArray[_timeIndex[1]]}',
                    onTap: () => _selectTime(context)),
                CustomDivider(),
                PrimaryLabel('主题'),
                EditTextField(
                  maxLines: 5,
                  maxLength: 400,
                  hintText: '请输入您的主题',
                  controller: _themeController,
                ),
                CustomDivider(),
                PrimaryLabel('主诉'),
                EditTextField(
                  maxLines: 5,
                  maxLength: 400,
                  hintText: '请输入您要主诉的内容',
                  controller: _contentController,
                ),
                CustomDivider(),
                PrimaryLabel(
                  '上传图片',
                  trailing: Text('${_images.length}/$maxImageCount'),
                ),
                Container(
                  color: Colors.white,
                  height: 110,
                  width: double.maxFinite,
                  alignment: Alignment.topLeft,
                  padding: EdgeInsets.all(10),
                  child: ListView.separated(
                    scrollDirection: Axis.horizontal,
                    itemBuilder: (c, i) {
                      if (i == _images.length) {
                        return ItemAdd(onTap: _selectImages);
                      } else {
                        return InkWell(
                          onTap: () {
                            CommonUtils.openGallery(
                                context,
                                _uploadedImages
                                    .map((e) => Urls.BASE_URL + e)
                                    .toList(),
                                i);
                          },
                          child: ItemImagePreview(
                            _images[i],
                            onTap: () {
                              // 删除图片时，判断已上传图片列表中是否包含这张照片。
                              if (_uploadedImages.length > i) {
                                _uploadedImages.removeAt(i);
                              }
                              setState(() {
                                _images.removeAt(i);
                              });
                            },
                          ),
                        );
                      }
                    },
                    itemCount: _images.length == maxImageCount
                        ? _images.length
                        : _images.length + 1,
                    padding: EdgeInsets.only(left: 0),
                    separatorBuilder: (BuildContext context, int index) {
                      // 给最后一个加号前面添加间距。
                      return SizedBox(
                        width: _images.length > 0 && index == _images.length - 1
                            ? 13
                            : 0,
                      );
                    },
                  ),
                ),
                CustomDivider(),
                PrimaryLabel('上传视频'),
                Container(
                  height: 100,
                  color: Colors.white,
                  padding: EdgeInsets.all(10),
                  alignment: Alignment.centerLeft,
                  child: _video == null
                      ? ItemAdd(onTap: _selectVideo)
                      : Stack(
                          children: [
                            Container(
                              child: InkWell(
                                child: ClipRRect(
                                  child: _futureImage,
                                  borderRadius:
                                      BorderRadius.all(Radius.circular(6)),
                                ),
                                onTap: () {
                                  Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                      builder: (c) => CustomVideoPlayer(
                                        _video.path,
                                        isLocalFile: true,
                                      ),
                                    ),
                                  );
                                },
                              ),
                              margin: EdgeInsets.all(5),
                            ),
                            Positioned(
                              right: 0,
                              top: 0,
                              child: InkWell(
                                child: Image.asset(
                                  'assets/images/ic_delete.png',
                                  width: 18,
                                  height: 18,
                                ),
                                onTap: () {
                                  setState(() {
                                    _video = null;
                                    _uploadedVideos.clear();
                                  });
                                },
                              ),
                            )
                          ],
                        ),
                ),
              ],
            ),
          ),
          PrimaryButton(
            '选择会诊医生',
            onPressed: () {
              // 将预选参数传递到下一页
              if (_department == null) {
                ToastUtil.show('请选择会诊科室', context);
                return;
              }
              if (_type == null) {
                ToastUtil.show('请选择会诊类型', context);
                return;
              }
              if (_timeIndex == null) {
                ToastUtil.show('请选择预约时间', context);
                return;
              }
              if (_themeController.text.trim().isEmpty) {
                ToastUtil.show('请输入会诊主题', context);
                return;
              }
              if (_contentController.text.trim().isEmpty) {
                ToastUtil.show('请输入您要主诉的内容', context);
                return;
              }
              final bean = ConsultationPostBean(
                doctorId: SPUtils.getUser().id,
                hospitalDeptId: _departments[_department].value,
                consultationTypeId: _consultationTypes[_type].value,
                title: _themeController.text.trim(),
                content: _contentController.text.trim(),
                freeTime: dateArray[_timeIndex[0]].toString().substring(0, 10),
                morningAfternoon: Constants.timeArray[_timeIndex[1]],
                appointmentImag: _uploadedImages.join(','),
              );
              if (_uploadedVideos.isNotEmpty) {
                bean.video = _uploadedVideos.first;
              }
              Navigator.push(context,
                  MaterialPageRoute(builder: (c) => SelectDoctorPage(bean)));
            },
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _themeController.dispose();
    _contentController.dispose();
  }

  @override
  void initState() {
    super.initState();
    // 取得接下来的一周时间，用于时间选择。
    DateTime now = DateTime.now();
    DateTime start = now.subtract(Duration(days: 2000));
    for (int i = 0; i < 2007; i++) {
      dateArray.add(start.add(Duration(days: i + 1)));
    }
    dateArray = dateArray.reversed.toList();
    // 获取弹窗数据。
    _getDepartmentTypes();
    _getConsultationTypes();
  }

  /// 获取会诊类型列表
  Future<void> _getConsultationTypes() async {
    var data = await XHttp.postJson(
        sprintf(Urls.DICT_VALUES, ['tab_consultation_ype']));
    if (data != null) {
      ListResponse response = ListResponse.fromJson(data);
      if (response.code == 1) {
        if (mounted) {
          _consultationTypes =
              List.from(response.data.map((e) => Department.fromJson(e)));
        }
      }
    }
  }

  /// 获取科室列表
  Future<void> _getDepartmentTypes() async {
    var data =
        await XHttp.postJson(sprintf(Urls.DICT_VALUES, ['section_type']));
    if (data != null) {
      ListResponse response = ListResponse.fromJson(data);
      if (response.code == 1) {
        if (mounted) {
          _departments =
              List.from(response.data.map((e) => Department.fromJson(e)));
        }
      }
    }
  }

  /// 选择科室
  void _selectDepartment(BuildContext context) async {
    CommonUtils.hideKeyboard(context);
    int value = await DialogUtils.showSelectOptionDialog(
        context, '选择科室', _departments.map((e) => e.label).toList(),
        selectedIndex: _department);
    if (mounted) {
      setState(() {
        _department = value;
      });
    }
  }

  void _selectImages() async {
    CommonUtils.hideKeyboard(context);
    try {
      List<Asset> value = await MultiImagePicker.pickImages(
        maxImages: maxImageCount,
        selectedAssets: _images,
      );
      if (mounted) {
        setState(() {
          _images = value;
        });
        if (_images.isNotEmpty) {
          _uploadImages();
        }
      }
    } on Exception catch (e) {
      Log.d(_tag, e);
    }
  }

  /// 选择会诊类型
  void _selectReserveType(BuildContext context) async {
    CommonUtils.hideKeyboard(context);
    int value = await DialogUtils.showSelectOptionDialog(
        context, '会诊类型', _consultationTypes.map((e) => e.label).toList(),
        selectedIndex: _type);
    if (mounted) {
      setState(() {
        _type = value;
      });
    }
  }

  /// 选择预约时间
  void _selectTime(BuildContext context) async {
    CommonUtils.hideKeyboard(context);
    var value = await DialogUtils.showSelectConsultationTimeDialog(
      context,
      '预约时间',
      dateArray
          .map((e) => '${sprintf('%02d', [e.year])}-${sprintf('%02d', [
                    e.month
                  ])}-${sprintf('%02d', [
                    e.day
                  ])} ${Constants.weekdays[e.weekday - 1]}')
          .toList(),
      Constants.timeArray,
      index1: _timeIndex == null ? 0 : _timeIndex[0] ?? 0,
      index2: _timeIndex == null ? 0 : _timeIndex[1] ?? 0,
    );
    if (mounted) {
      setState(() {
        _timeIndex = value;
      });
    }
  }

  /// 选择视频
  void _selectVideo() async {
    CommonUtils.hideKeyboard(context);
    showDialog(
        context: context,
        builder: (c) {
          return SimpleDialog(
            title: Text('上传视频'),
            children: [
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('从相册选取'),
                ),
                onPressed: () => _selectVideoFromGallery(0),
              ),
              SimpleDialogOption(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Text('使用相机拍摄'),
                ),
                onPressed: () => _selectVideoFromGallery(1),
              ),
            ],
          );
        });
  }

  void _selectVideoFromGallery(int index) async {
    Navigator.pop(context);
    if (await Permission.camera.request().isGranted) {
      var data = await _picker.getVideo(
        source: index == 0 ? ImageSource.gallery : ImageSource.camera,
        maxDuration: Duration(seconds: 30),
      );
      if (mounted) {
        setState(() {
          _video = data;
          _futureImage = GenThumbnailImage(
              thumbnailRequest: ThumbnailRequest(
                  video: _video.path,
                  thumbnailPath: null,
                  imageFormat: ImageFormat.JPEG,
                  maxHeight: 200,
                  maxWidth: 200,
                  timeMs: 0,
                  quality: 50));
          if (_video != null) {
            _uploadVideos();
          }
        });
      }
      Log.d(_tag, '${_video?.path}');
    } else {
      openAppSettings();
    }
  }

  /// 图片上传
  void _uploadImages() async {
    DialogUtils.showWaitDialog(context);
    FormData formData = FormData.fromMap({});
    formData.files.addAll((await CommonUtils.images2MapEntry(_images)));
    var value = await XHttp.uploadFiles(
      Urls.UPLOAD,
      formData,
    );
    if (value != null) {
      ListResponse response = ListResponse.fromJson(value);
      if (response.code == 1) {
        _uploadedImages = List<String>.from(response.data);
      }
    }
    Navigator.pop(context);
  }

  /// 视频上传
  void _uploadVideos() async {
    DialogUtils.showWaitDialog(context);
    FormData formData = FormData.fromMap({});
    formData.files.addAll((await CommonUtils.files2MapEntry([_video])));
    var value = await XHttp.uploadFiles(
      Urls.UPLOAD,
      formData,
    );
    if (value != null) {
      ListResponse response = ListResponse.fromJson(value);
      if (response.code == 1) {
        _uploadedVideos = List<String>.from(response.data);
      }
    }
    Navigator.pop(context);
  }
}

class ThumbnailRequest {
  final String video;
  final String thumbnailPath;
  final ImageFormat imageFormat;
  final int maxHeight;
  final int maxWidth;
  final int timeMs;
  final int quality;

  const ThumbnailRequest(
      {this.video,
      this.thumbnailPath,
      this.imageFormat,
      this.maxHeight,
      this.maxWidth,
      this.timeMs,
      this.quality});
}

class ThumbnailResult {
  final Image image;
  final int dataSize;
  final int height;
  final int width;

  const ThumbnailResult({this.image, this.dataSize, this.height, this.width});
}

class GenThumbnailImage extends StatefulWidget {
  final ThumbnailRequest thumbnailRequest;

  const GenThumbnailImage({Key key, this.thumbnailRequest}) : super(key: key);

  @override
  _GenThumbnailImageState createState() => _GenThumbnailImageState();
}

class _GenThumbnailImageState extends State<GenThumbnailImage> {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<ThumbnailResult>(
      future: genThumbnail(widget.thumbnailRequest),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData) {
          final _image = snapshot.data.image;
          return _image;
        } else if (snapshot.hasError) {
          return Container(
            padding: EdgeInsets.all(8.0),
            color: Colors.red,
            child: Text(
              "Error:\n${snapshot.error.toString()}",
            ),
          );
        } else {
          return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                CircularProgressIndicator(),
              ]);
        }
      },
    );
  }
}

Future<ThumbnailResult> genThumbnail(ThumbnailRequest r) async {
  Uint8List bytes;
  final Completer<ThumbnailResult> completer = Completer();
  if (r.thumbnailPath != null) {
    final thumbnailPath = await VideoThumbnail.thumbnailFile(
        video: r.video,
        thumbnailPath: r.thumbnailPath,
        imageFormat: r.imageFormat,
        maxHeight: r.maxHeight,
        maxWidth: r.maxWidth,
        timeMs: r.timeMs,
        quality: r.quality);

    print("thumbnail file is located: $thumbnailPath");

    final file = File(thumbnailPath);
    bytes = file.readAsBytesSync();
  } else {
    bytes = await VideoThumbnail.thumbnailData(
        video: r.video,
        imageFormat: r.imageFormat,
        maxHeight: r.maxHeight,
        maxWidth: r.maxWidth,
        timeMs: r.timeMs,
        quality: r.quality);
  }

  int _imageDataSize = bytes.length;
  print("image size: $_imageDataSize");

  final _image = Image.memory(bytes, width: 70, height: 70, fit: BoxFit.cover);
  _image.image
      .resolve(ImageConfiguration())
      .addListener(ImageStreamListener((ImageInfo info, bool _) {
    completer.complete(ThumbnailResult(
      image: _image,
      dataSize: _imageDataSize,
      height: info.image.height,
      width: info.image.width,
    ));
  }));
  return completer.future;
}
